package main

import "fmt"

func main() {
	// go没有函数重载，函数名不能重复定义
	result := foo(3, 5)

	fmt.Println("结果是：", result)

	before, after := bar(10, 4, "unused")
	fmt.Println("结果是：", before, after)

	sum, diff := gkd(20, 8)
	fmt.Println("结果是：", sum, diff)

	p := next()
	fmt.Println(*p)

	total := add(1, 2, 3, 4, 5)
	fmt.Println("总和是：", total)

	makeAddFunc := makeAdd()
	fmt.Println("函数作为返回值结果是：", makeAddFunc(7, 8))

	// 匿名函数 立即执行（IIFE）当闭包用
	func(a, b int) {
		fmt.Println("匿名函数结果是：", a*b)
	}(6, 9)

	// operation 是一个函数类型的变量
	operation := func(a, b int) int { return a * b }
	fmt.Println("函数作为参数结果是：", apply(4, 5, operation))

}

// 定义一个函数
func foo(a int, b int) int {
	return a + b
}

// 接受两个整数参数，一个匿名参数、返回两个整数值
func bar(a, b int, _ string) (int, int) {
	return a + b, a - b
}

// 带有变量名的返回值
func gkd(a int, b int) (sum int, diff int) {
	sum = a + b
	diff = a - b
	return // 直接使用 return 语句返回，返回值会自动带上名称
}

// 返回局部变量地址
func next() *int {
	i := 10
	return &i // 逃逸分析会把 i 抬到堆，安全
}

// 可变参数函数
func add(nums ...int) int {
	s := 0
	for _, v := range nums {
		s += v
	}
	return s
}

// 函数作为返回值
type op func(int, int) int // 定义函数类型
func makeAdd() op {
	return func(a, b int) int { return a + b }
}

// 函数作为参数
func apply(a int, b int, fn op) int {
	return fn(a, b)
}
